package com.fruit.service.lightpay.impl;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.fruit.constants.PayConstant;
import com.fruit.mapper.lightpay.LightPayMapper;
import com.fruit.mapper.sys.SysMapper;
import com.fruit.pojo.lightpay.LightPayCashier;
import com.fruit.pojo.lightpay.LightPayCashierAlipay;
import com.fruit.pojo.lightpay.LightPayCashierWechat;
import com.fruit.pojo.pay.TransactionFlow;
import com.fruit.pojo.sys.AlipayConfig;
import com.fruit.pojo.sys.WechatConfig;
import com.fruit.service.lightpay.LightPayManager;
import com.fruit.service.pay.PayManager;
import com.fruit.util.CommonUtil;
import com.fruit.util.CustomUtil;
import com.fruit.util.DateUtil;
import com.fruit.util.HttpClientManagerT;
import com.fruit.util.RequestHandler;
import com.fruit.util.ResultInfo;
import com.fruit.util.ResultUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class LightPayService implements LightPayManager{

	
	@Autowired
	private PayManager payService;
	
	@Autowired
	private SysMapper sysMapper;
	
	@Autowired
	private LightPayMapper lightPayMapper;	
	
	@Value("${alipay.money}")
	private String alipayMoney;
	
	@Value("${wechat.money}")
	private String xwMoney;
	
	@Value("${domain}")
	private String domain;
	
	public Map<String, Object> getTransactionFlow(String tradeId,String transactionCode){
		Map<String, Object> resMap = new HashMap<String, Object>();
		log.info("[{}]-【查看交易流水】-【开始】",tradeId);
		try{
		TransactionFlow tf = payService.getTransactionFlow(transactionCode);
		
		if(tf == null){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "交易订单不存在"));
			return resMap;
		}
		if(!PayConstant.State.notpay.equals(tf.getState())){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "交易订单已取消或已支付"));
			return resMap;
		}
		
		resMap.put("price", tf.getPayPrice());
		resMap.put("transactionCode", transactionCode);
		resMap.put("result", ResultUtil.initResult(ResultInfo.SUCCESS, "OK", "查询成功"));
		return resMap;
		}finally{
			ResultInfo ri = (ResultInfo)resMap.get("result");
			if(ResultInfo.ERROR.equals(ri.getState())){
				log.error("[{}]-【查看交易流水】-【异常】-【{}：{}】",tradeId,ri.getCode(),ri.getMessage());
			}else{
				log.info("[{}]-【查看交易流水】-【成功】",tradeId);	
			}
			log.info("[{}]-【查看交易流水】-【结束】",tradeId);	
		}
		
	}

	public Map<String, Object> validation(LightPayCashier lpc){
		Map<String, Object> resMap = new HashMap<String, Object>();
		if(StringUtils.isEmpty(lpc.getTransactionCode())){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "参数有误"));
			return resMap;	
		}
		
		int userId = lpc.getUserId();
		if(userId <= 0){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "用户不存在"));
			return resMap;	
		}
		
		//验证金额
		if(lpc.getPrice() == null || lpc.getPrice().compareTo(BigDecimal.ZERO) <= 0){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "支付金额有误"));
			return resMap;	
		}
		
		TransactionFlow tf = payService.getTransactionFlow(lpc.getTransactionCode());
		
		if(tf == null){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "交易订单不存在"));
			return resMap;
		}
		if(!PayConstant.State.notpay.equals(tf.getState())){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "交易订单已取消或已支付"));
			return resMap;
		}
		if(lpc.getPrice().compareTo(tf.getPayPrice()) != 0){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "支付金额有误"));
			return resMap;	
		}
		
		LightPayCashier lpcnew = lightPayMapper.getLightpayCashierByTCode(tf.getCode());
		if(lpcnew != null && !PayConstant.State.notpay.equals(lpcnew.getState())){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "交易订单已取消或已支付"));
			return resMap;
		}
		
		String curTime = DateUtil.getTime();
		if(lpcnew != null){
			lpc.setId(lpcnew.getId());
			lpc.setRemark(lpcnew.getRemark());
			lpc.setCode(lpcnew.getCode());
		}else{
			//插入收银记录
			lpc.setRemark(tf.getRemark());
			lpc.setCreateTime(curTime);
			lpc.setState(PayConstant.State.notpay.getValue());
			lightPayMapper.saveLightpayCashier(lpc);
			lpc.setCode(CustomUtil.orderCode(3, lpc.getId(), lpc.getUserId()));
			int num = lightPayMapper.updateLightpayCashierCode(lpc);
			if(num != 1){
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "confirm_again", "请重新结算!", null, ResultInfo.ROLLBACK));
				return resMap;
			}
		}
		resMap.put("tf", tf);
		resMap.put("result", ResultUtil.initResult(ResultInfo.SUCCESS, "OK", "校验成功"));
		
		return resMap;
		
	}
	
	@Override
	public Map<String, Object> saveAlipayPayCashier(String tradeId,LightPayCashier lpc) {
		log.info("[{}]-【支付宝支付】-【交易流水号：{}】-【用户：{}】-【开始】",tradeId,lpc.getTransactionCode(),lpc.getUserId());
		Map<String, Object> resMap = new HashMap<String, Object>();
		try{
		//验证参数
		log.info("[{}]-【支付宝支付】-【验证参数】",tradeId);
		lpc.setPayMode(PayConstant.PayMode.alipay.getValue());
		resMap = validation(lpc);
		ResultInfo ri = (ResultInfo)resMap.get("result");
		if(ResultInfo.ERROR.equals(ri.getState()) ){
			return resMap;
		}
		AlipayConfig ac = sysMapper.getAlipayConfig();
		if(ac == null){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "系统异常"));
			return resMap;
		}		
		log.info("[{}]-【支付宝支付】-【生成记录】",tradeId);
		LightPayCashierAlipay lpca = lightPayMapper.getLightpayCashierAlipay(lpc.getId());
		if(lpca == null){
			lpca = new LightPayCashierAlipay();
			lpca.setCashierId(lpc.getId());
			if(PayConstant.PayValue.test.equals(ac.getPayValue())){
				lpca.setTotalAmount(alipayMoney);
			}else{
				lpca.setTotalAmount(lpc.getPrice().toString());
			}
			lpca.setTimeStart(lpc.getCreateTime());
			lpca.setSellerId(ac.getSellerId());
			lightPayMapper.saveLightpayCashierAlipay(lpca);
		}else{
			if(PayConstant.RHandelState.yes.equals(lpca.getState())){
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "交易订单已取消或已支付"));
				return resMap;
			}
		}
		log.info("[{}]-【支付宝支付】-【封装支付宝参数】",tradeId);
		Map<String, String> returnParams = new HashMap<String, String>();
		returnParams.put("outTradeNo", lpc.getCode());
		returnParams.put("subject", lpc.getRemark());
		returnParams.put("totalAmount", lpca.getTotalAmount());
		returnParams.put("body", "共花费金额" + lpca.getTotalAmount() + "元");
		returnParams.put("appId", ac.getAppId());
		returnParams.put("returnUrl", domain+ac.getReturnUrl()+"?code="+lpc.getCode());
		returnParams.put("notifyUrl", domain+ac.getNotifyUrl());
		returnParams.put("sellerId", ac.getSellerId());
		returnParams.put("timeOutExpress", ac.getTimeOutExpress());
		returnParams.put("alipayPublicKey", ac.getAlipayPublicKey());
		returnParams.put("appPrivateKey", ac.getAppPrivateKey());
		returnParams.put("charset", ac.getCharset());
		returnParams.put("gateWayUrl", ac.getGateWayUrl());
		resMap.put("returnParams", returnParams);
		resMap.put("result", ResultUtil.initResult(ResultInfo.SUCCESS, "OK", "保存成功"));
		return resMap;
		}finally{
			ResultInfo ri = (ResultInfo)resMap.get("result");
			if(ResultInfo.ERROR.equals(ri.getState())){
				log.error("[{}]-【支付宝支付】-【异常】-【{}：{}】",tradeId,ri.getCode(),ri.getMessage());
			}else{
				log.info("[{}]-【支付宝支付】-【成功】",tradeId);	
			}
			log.info("[{}]-【支付宝支付】-【结束】",tradeId);	
		}
		
		
	}

	@Override
	public Map<String, Object> saveWechatPayCashier(String tradeId,LightPayCashier lpc) {
		log.info("[{}]-【微信支付】-【交易流水号：{}】-【用户：{}】-【开始】",tradeId,lpc.getTransactionCode(),lpc.getUserId());
		Map<String, Object> resMap = new HashMap<String, Object>();
		try{
		//验证参数
		log.info("[{}]-【微信支付】-【验证参数】",tradeId);
		lpc.setPayMode(PayConstant.PayMode.wechat.getValue());
		resMap = validation(lpc);
		ResultInfo ri = (ResultInfo)resMap.get("result");
		if(ResultInfo.ERROR.equals(ri.getState()) ){
			return resMap;
		}
		WechatConfig wc = sysMapper.getWechatConfig();
		if(wc == null){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "系统异常"));
			return resMap;
		}
		log.info("[{}]-【微信支付】-【生成记录】",tradeId);
		LightPayCashierWechat lpcw = lightPayMapper.getLightpayCashierWechat(lpc.getId());
		RequestHandler reqH = new RequestHandler();
		reqH.setKey(wc.getApiKey());
		if(lpcw == null){
			String totalFee = null;
			if(PayConstant.PayValue.test.equals(wc.getPayValue())){
				totalFee = xwMoney;
			}else{
				totalFee = CustomUtil.getMoney(lpc.getPrice());
			}
			reqH.setParameters("appid", wc.getAppId());
			reqH.setParameters("mch_id", wc.getMchId());
			reqH.setParameters("nonce_str", CommonUtil.getNonceStr());
			reqH.setParameters("body", lpc.getRemark());
			reqH.setParameters("out_trade_no", lpc.getCode());
			reqH.setParameters("total_fee", totalFee);
			reqH.setParameters("spbill_create_ip", lpc.getIp());
			reqH.setParameters("notify_url", domain + wc.getNotifyUrl());
			reqH.setParameters("trade_type", PayConstant.WechatPayType.APP.getValue());
			String xmlParams = reqH.parseXML();
			log.info("[{}]-【微信支付】-【生成prepay_id】-【请求参数：{}】",tradeId,xmlParams);
			String xmlRes = HttpClientManagerT.postData(HttpClientManagerT.getPostMethod(wc.getCreateOrderUrl()), xmlParams);
			log.info("[{}]-【微信支付】-【返回prepay_id】-【返回参数：{}】",tradeId,xmlRes);
			Map<String, String> mapRes = CommonUtil.xmlBody2map(xmlRes, "xml");
			if(mapRes == null || mapRes.isEmpty()){
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "微信调用失败!"));
				return resMap;
			}
			String returnCode = mapRes.get("return_code");
			String resultCode = mapRes.get("result_code");
			if(!(PayConstant.CODE_SUCCESS.equals(returnCode)
					&& PayConstant.CODE_SUCCESS.equals(resultCode))){
				System.out.println(mapRes);
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "微信调用失败!"));
				return resMap;
			}
			
			//生成支付附记录
			lpcw = new LightPayCashierWechat();
			lpcw.setCashierId(lpc.getId());
			lpcw.setTradeType(PayConstant.WechatPayType.APP.getValue());
			lpcw.setReqContent(xmlParams);
			lpcw.setTimeStart(DateUtil.getSdfTimes());
			lpcw.setTotalFee(totalFee);
			lpcw.setPrepayId(mapRes.get("prepay_id"));
			lpcw.setRespContent(xmlRes);
			lightPayMapper.saveLightpayCashierWechat(lpcw);
		}else{
			if(PayConstant.RHandelState.yes.equals(lpcw.getState())){
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "交易订单已取消或已支付"));
				return resMap;
			}
		}
		
		log.info("[{}]-【微信支付】-【封装微信支付参数】",tradeId);
		Map<String, String> prePayInfo = new TreeMap<String, String>();
		prePayInfo.put("appid", wc.getAppId());
		prePayInfo.put("package", "Sign=WXPay");
		prePayInfo.put("partnerid", wc.getMchId());
		prePayInfo.put("prepayid", lpcw.getPrepayId());
		prePayInfo.put("timestamp", CommonUtil.getTimeStamp());
		prePayInfo.put("noncestr", CommonUtil.getNonceStr());
		String paySign = reqH.createSign(prePayInfo);
		prePayInfo.put("sign", paySign);
		prePayInfo.put("returnUrl", domain+wc.getReturnUrl()+"?code="+lpc.getCode());
		resMap.put("prePayInfo", prePayInfo);
		log.info("[{}]-【微信支付】-【封装微信支付参数】-【结果：{}】",tradeId,prePayInfo);
		resMap.put("result", ResultUtil.initResult(ResultInfo.SUCCESS, "OK", "保存成功"));	
		
		return resMap;
		}finally{
			ResultInfo ri = (ResultInfo)resMap.get("result");
			if(ResultInfo.ERROR.equals(ri.getState())){
				log.error("[{}]-【微信支付】-【异常】-【{}：{}】",tradeId,ri.getCode(),ri.getMessage());
			}else{
				log.info("[{}]-【微信支付】-【成功】",tradeId);	
			}
			log.info("[{}]-【微信支付】-【结束】",tradeId);	
		}
	}

	@Override
	public Map<String, Object> getLightpayCashierByCode(String code) {
		Map<String, Object> resMap = new HashMap<String, Object>();
		LightPayCashier lpc = lightPayMapper.getLightpayCashierByCode(code);
		if(lpc == null){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "收银不存在"));
			return resMap;	
		}
		TransactionFlow tf = payService.getTransactionFlow(lpc.getTransactionCode());
		if(tf == null){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "交易流水不存在"));
			return resMap;	
		}
		
		resMap.put("tf", tf);
		resMap.put("result", ResultUtil.initResult(ResultInfo.SUCCESS, "OK", "查看成功"));
		return resMap;
	}
	
	
}
